#include "demo_utils.hpp"

#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>

namespace atomic_examples {
namespace {

/**
 * @brief 简易的引用计数基类。
 *
 * 特性说明：
 *  - 内部维护一个 `std::atomic<size_t>` 计数。
 *  - `addRef()` / `release()` 提供线程安全的引用增减操作。
 */
class RefCounted {
public:
  /**
   * @brief 增加引用次数。
   *
   * 使用 memory_order_relaxed，因为我们只需要原子性，不涉及其他数据同步。
   */
  void addRef() {
    ref_count_.fetch_add(1, std::memory_order_relaxed);
  }

  /**
   * @brief 释放一次引用，并在计数归零时销毁自身。
   *
   * ⚠️ 使用 memory_order_acq_rel，确保对象被销毁前所有写入对其他线程可见。
   */
  void release() {
    if (ref_count_.fetch_sub(1, std::memory_order_acq_rel) == 1) {
      delete this;
    }
  }

protected:
  RefCounted() = default;
  virtual ~RefCounted() = default;

private:
  std::atomic<std::size_t> ref_count_{1}; ///< 引用计数初始为 1。
};

/**
 * @brief 继承自 RefCounted 的示例资源类。
 *
 * 用于模拟多线程环境下共享资源的生命周期管理。
 */
class SharedResource : public RefCounted {
public:
  /**
   * @brief 工厂方法，返回新建的 SharedResource 实例。
   */
  static SharedResource* create() {
    return new SharedResource();
  }

  /**
   * @brief 模拟执行某项工作。
   */
  void doWork() const {
    std::cout << "SharedResource working on thread "
              << std::this_thread::get_id() << '\n';
  }

private:
  SharedResource() = default;

  ~SharedResource() override {
    std::cout << "SharedResource destroyed\n";
  }
};

/**
 * @brief 演示原子引用计数确保资源在多线程下正确析构。
 */
void runRefCountDemo() {
  printHeader("Atomic Reference Counting Example");

  SharedResource* resource = SharedResource::create(); ///< 主线程持有的初始引用。

  constexpr int kThreads = 4;
  std::vector<std::thread> threads;
  threads.reserve(kThreads);

  auto worker = [resource]() {
    resource->addRef();  ///< ✅ 获取额外引用，避免并发使用时资源被提前销毁。
    resource->doWork();
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    resource->release();
  };

  for (int i = 0; i < kThreads; ++i) {
    threads.emplace_back(worker);
  }
  for (auto& t : threads) {
    t.join();
  }

  resource->release();  ///< ✅ 释放主线程引用，引用计数归零时资源会自动析构。
}

} // namespace
} // namespace atomic_examples

int main() {
  atomic_examples::runRefCountDemo();
  return 0;
}